//
// Created by martin on 2/8/22.
//

#ifndef MUDUO_CHANNEL_H
#define MUDUO_CHANNEL_H

#include "muduo/base/noncopyable.h"
#include "muduo/base/Timestamp.h"

#include <memory>
#include <functional>

namespace muduo
{
namespace net
{
class EventLoop;

/**
 * One fd listened by poll per Channel.
 * Dispatch IO event for one fd, but do not own the fd,
 * or close the fd when destruct.
 * Caller defines EventCallback including read/write/error/close event for fd.
 *
 * Only owner EventLoop in the IO thread can invoke it, so thread safe is not necessary.
 */

/**
 * Channel绑定一个fd, 用于设置fd上要监听的事件, 以及相应的回调函数.
 * Poller监听到有通道绑定的事件发生, 就会将其加入激活的通道列表,
 * 然后在EventLoop::loop()中调用该Channel对应事件注册的回调函数
 */
class Channel : private noncopyable
{
public:
    typedef std::function<void()> EventCallback;
    typedef std::function<void(Timestamp)> ReadEventCallback;

    Channel(EventLoop* loop, int fd__);
    ~Channel();

    /* 处理事件，监听事件激活时，由EventLoop::loop调用 */
    void handleEvent(Timestamp recevieTime);
    /* 设置事件回调，由Channel对象持有者配置Channel事件回调时调用 */
    void setReadCallback(ReadEventCallback cb)
    { readCallback_ = std::move(cb); }
    void setWriteCallback(EventCallback cb)
    { writeCallback_ = std::move(cb); }
    void setCloseCallback(EventCallback cb)
    { closeCallback_ = std::move(cb); }
    void setErrorCallback(EventCallback cb)
    { errorCallback_ = std::move(cb); }

    /* 将shared_ptr管理的对象系到本地weak_ptr管理的tie_, 可用于保存TcpConnection指针 */
    void tie(const std::shared_ptr<void>&);

    int fd() const { return fd_; }
    int events() const { return events_; }
    void set_revents(int revt) { revents_ = revt; } // used by poller
//    int revents() const { return revents_; }
    bool isNoneEvent() const { return events_ == kNoneEvent; }

    /* 使能/禁用 监听 可读/可写事件, 会影响Poller监听的通道列表 */
    void enableReading() { events_ |= kReadEvent; update(); }
    void disableReading() { events_ &= ~kReadEvent; update(); }
    void enableWriting() { events_ |= kWriteEvent; update(); }
    void disableWriting() { events_ &= ~kWriteEvent; update(); }
    void disableAll() { events_ = kNoneEvent; update(); }
    /* 判断是否请求监听 可写事件 */
    bool isWriting() const { return events_ & kWriteEvent; }
    /* 判断是否请求监听 可读事件 */
    bool isReading() const { return events_ & kReadEvent; }

    // for Poller
    int index() { return index_; }
    void set_index(int idx) { index_ = idx; }

    // for debug
    string reventsToString() const;
    string eventsToString() const;

    void doNotLogHup() { logHup_ = false; }

    EventLoop* ownerLoop() { return loop_; }
    /* 从EventLoop中移除当前通道.
     * 调用前确保已调用disableAll, 即在移除前禁用所有事件
     */
    void remove();

private:
    /* 将fd对应事件转化为字符串 */
    static string eventsToString(int fd, int ev);
    /* update()将调用EventLoop::updateChannel更新监听的通道 */
    void update();
    /* 根据不同的事件源激活不同的回调函数，来处理事件 */
    void handleEventWithGuard(Timestamp receiveTime);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop* loop_;
    const int fd_; // file descriptor
    int events_;   // request events, set by user_
    int revents_;  // returned events, current active events, set by EventLoop/Poller
    // used by Poller
    // PollPoller: index of poll fds array mapped to fd_
    // EPollPoller: operation type for fd: kNew, kAdded, kDeleted
    int index_;
    bool logHup_;

    // TcpConnection持有Channel的 unique_ptr,
    // Channel要持有TcpConnection只能用weak_ptr不能用shared_ptr, 否则可能导致循环引用
    std::weak_ptr<void> tie_;
    bool tied_;
    bool eventHandling_;
    bool addedToLoop_;
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};

} // namespace muduo
} // namespace net



#endif //MUDUO_CHANNEL_H
